package mathy.wili.c.asm;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import mathy.c.Ca;
import mathy.wili.c.Class9;
import mathy.wili.c.MiscFilter.ClsFilter;
import net.bytebuddy.jar.asm.ClassReader;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.Opcodes;
//import jdk.internal.org.objectweb.asm.ClassReader;
//import jdk.internal.org.objectweb.asm.Opcodes;
//import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
//import jdk.internal.org.objectweb.asm.tree.ClassNode;
//import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
//import jdk.internal.org.objectweb.asm.tree.MethodNode;
/**
 * 
 * @author weila 2021年2月18日
 */
@SuppressWarnings("rawtypes")
public class Asm9 {
	static int UseLog = -1, FunVisitor_useLog = -1;

	static final int AsmVerion = Opcodes.ASM5;

	static final String INIT = "<init>", CLINIT = "<clinit>";//初始化、静态初始化
	static Class<?> asmType(net.bytebuddy.jar.asm.Type type) {
		return Class9.classOfName(type.getClassName(), -1);
	}

	static Class<?>[] classesOfAsmTypes(net.bytebuddy.jar.asm.Type[] types) {
		Class<?>[] ret = new Class<?>[types.length];
		for (int i = 0; i < types.length; i++) {
			ret[i] = Class9.classOfName(types[i].getClassName(), -1);
		}
		return ret;
	}

	static Executable methodOf(Class<?> clazz, String funName, Class<?>[] paramTypes) {
		try {
			if (funName.equals(INIT) || funName.equals(clazz.getSimpleName())) {
				Constructor<?> cons = clazz.getDeclaredConstructor(paramTypes);
				return cons;
			} else {
				if (funName.equals(CLINIT))
					return null;
				if (++inc == 128)
					Ca.pause();
				Method md = Class9.findMethodUpwards(1, clazz, funName, paramTypes);
				return md;
			}
		} catch (Throwable e) {
			return null;
		}
	}

	/**
	 * 	访问静态块 | 非静态块 | 静态属性 | 非静态属性，不访问未初始化的属性
	 */
	public static AsmItems findInInit_forCalledMethods_and_fields(Class<?> clazz, int initOpt, ClassReader read,
			ClsFilter clsFilter, AsmItems toList) {
		//不会访问未初始化的属性
		AsmCont cont = new AsmCont(toList);
		findCalledMethods_and_fields_fromMethod00(clazz, null, initOpt, read, clsFilter, cont);
		return toList;
	}

	/**
	 * 	在方法中查找：属性|方法|类型
	 */
	public static AsmItems findInMethod_forCalledMethods_and_fields(Class<?> clazz, Executable method, ClassReader read,
			ClsFilter clsFilter, AsmItems toList) {
		if (toList == null)
			toList = new AsmItems2();
		AsmCont cont = new AsmCont(toList);
		findCalledMethods_and_fields_fromMethod00(clazz, method, -1, read, clsFilter, cont);
		return toList;
	}

	static ClassReader newClassReader(String name) {
		try {
			return new ClassReader(name);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 *  Find all called method|constructor|field|type in method.
	 */
	private static void findCalledMethods_and_fields_fromMethod00(Class clazz, Executable method, int initOpt,
			ClassReader read, ClsFilter filt, AsmCont cont) {
		//常量所在字段似乎无法访问，或不存在于字节码中。
		//staticInit: 静态1|非静态2|所有3
		if (read == null) {
			read = newClassReader(clazz.getName());
			if (read == null)
				return;
		}
		if (method != null && method.getName().equals("wili.c.asm.ClsVisitor"))
			Ca.pause();
		ClassVisitor visit = new ClsVisitor(null, clazz, filt, cont).setInitOpt(initOpt).setMethod(method);
		read.accept(visit, Asm9.AsmVerion);
	}

	/**
	 * 	把类中的【静态常量简单值】属性修改成【静态属性】。
	 */
	public static Class<?> removeFinalModifier_fromStaticFinalSimpleFields__(Class<?> fileCls, File clsFile) {
		//这样做的目的是，我难以访问【静态常量简单值】，若去掉final属性则必可访问到
		//表面上好象可以，但引起类加载，等问题。
		return Coms2b.removeFinalModifier_fromStaticFinalSimpleFields(fileCls, clsFile);
	}
	static int inc;
}